#include "demoWindow.h"
#include <math.h>
#include <iostream>
#include <cstdlib>

#include "ShaderBase.h"
#include "Shader.h"
#include "ShaderLoader.h"

#include "Lumiere.h"
#include "camera.h"
#include "SkyBox.h"
#include "ObjetMNT.h"
#include "ObjetOFF.h"
#include "ObjetIMG.h"

#include "recordGL.h"

using namespace std;
#define PI 3.14
#define DEG2RAD 3.14159/180.0

float angle=0;
float X=0,Y=0,Z=0,COS=0,inc=0.2,E=1;
bool charge=false, blight=true;
int choice =0;

ObjetMNT terrain;
ObjetOFF tricep;
ObjetOFF navette;
ObjetOFF station;
ObjetIMG masson;
ObjetIMG hurault;

camera cam;
Lumiere light;
SkyBox skybox;
recordGL myrec("./", 800 ,600);

bool firstNav=true, firstSta=true;
float CoordAuxX=0.,CoordAuxY=0.,CoordAuxZ=0.;
Vector3D CoordAux;
float anglX=0.,anglY=0.;
float k = 0.;

void Effets(int selection)
{ 	
  switch (selection)
    {	
    case 0 :glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);break; 
    case 1 :glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);break; 
    case 2 :choice = 0;break; 
    case 3 :choice = 1;break;
    case 4 :choice = 2;break; 
   
    case 6 :exit(0);break; 
    }		
  glutPostRedisplay();	
}

void sMenu1(int selection)
{ 
  std::cout<<"sMenu "<<selection<<std::endl;
  switch (selection)
    {	
    case 0 :;break; 
    }	
  glutPostRedisplay();	
}
void sMenu2(int selection)
{ 
  std::cout<<"sMenu2 "<<selection<<std::endl;
  glutPostRedisplay();
}


int sMenu,sMenu_2,mainMenu;

void menu(){
	
  sMenu = glutCreateMenu(sMenu1);
  glutAddMenuEntry("Buddha",0);
	
  sMenu_2 = glutCreateMenu(sMenu2);
  glutAddMenuEntry("1",1);
  glutAddMenuEntry("10",10);
  glutAddMenuEntry("20",20);
	
  mainMenu = glutCreateMenu(Effets);
  glutAddMenuEntry("Mode plein",1);
  glutAddMenuEntry("Mode fil de fer",0);
  glutAddMenuEntry("Mode Free Fly",2);
  glutAddMenuEntry("Mode Vue Navette",3);
  glutAddMenuEntry("Mode Vue Station",4);
	
	
  // glutAddSubMenu("Activation Figures",
  // 		 sMenu);
  // glutAddSubMenu("Mon second sous menu",
  // 		 sMenu_2);
  glutAddMenuEntry("Quitter",6);
  glutAttachMenu(GLUT_MIDDLE_BUTTON);	
	
}

DemoWindow::DemoWindow(GlutMaster * glutMaster,
                       int setWidth, int setHeight,
                       int setInitPositionX, int setInitPositionY,
                       std::string title): rep(1){
  refglutMaster=glutMaster;
  width  = setWidth;               
  height = setHeight;
  initPositionX = setInitPositionX;
  initPositionY = setInitPositionY;
  
  glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
  glutInitWindowSize(width, height);
  glutInitWindowPosition(initPositionX, initPositionY);
  //   glViewport(0, 0, width, height);   // This may have to be moved to after the next line on some platforms
  
  glutMaster->CallGlutCreateWindow((char*) title.c_str(), this);
  
  menu();
  
  glViewport(0, 0, width, height);   // moved bu EM 
  
  glEnable(GL_DEPTH_TEST);
   
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity(); 

  glClearColor(1., 1., 1., 1.);

  GLenum code = glewInit();
  if(code != GLEW_OK)
    {
      cout<<"Couldn't initialize extension :";
      cout<< glewGetErrorString(code) << "\n";
    }
  else
    cout<<"OpenGL extensions loaded"<<endl;
}

DemoWindow::~DemoWindow(){
  glutDestroyWindow(windowID);
}


void DemoWindow::CallBackDisplayFunc(void){
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();
  //glRotated(angle,0,1,0);
  //gluLookAt ( 0,0,200,  0,0,0, 0,0,1 );
  glTranslated(X, Y, Z);
 

  cam.animate(150);
  cam.look();

  if(!charge)
    {
      skybox.Initialize();

      navette.setFilename("fichiers/x29_plane.off");
      navette.colorer(25,200,25,1);
      navette.move(412.,412.,150.);
      navette.rotate(0.,0.,0.);
      navette.set_mat_Ambiente(0.,0., 1., 1.0);
      navette.set_mat_Diffuse(0., 0.8, 1., 1.0);
      navette.set_mat_Speculaire(0., 0., 1., 1.0);
      navette.charger();
      navette.set_shininess(0.5);

      station.setFilename("fichiers/space_station2.off");
      station.colorer(150,150,150,1);
      station.move(412.,412.,170.);
      station.rotate(0.,0.,0.);
      station.charger();
      station.set_mat_Ambiente(1.0,0., 0., 1.0);
      station.set_mat_Diffuse(1.,0., 0., 1.0);
      station.set_mat_Speculaire(1.0,0.,0., 1.0);
      station.set_shininess(0.5);

      tricep.setFilename("fichiers/triceratops.off");
      tricep.colorer(0,255,0,1);//(200,150,30,1);
      tricep.move(25., 25., 95.);
      tricep.charger();
      tricep.setAngleX(90.);
      tricep.set_mat_Ambiente(0.,1.8, 1., 1.0);
      tricep.set_mat_Diffuse(0., 1.8, 1., 1.0);
      tricep.set_mat_Speculaire(0., 1.9, 1., 1.0);
      tricep.set_shininess(0.5);

      terrain.setFilename("fichiers/mouillere2.txt");
      terrain.setTexname("fichiers/images/mouillere2.png");
      terrain.charger();
      terrain.set_mat_Ambiente(0.9, 0.9, 0.9, 1.0);
      terrain.set_mat_Diffuse(0.9, 0.9, 0.9, 1.0);
      terrain.set_mat_Speculaire(0.9, 0.9, 0.9, 1.0);
      terrain.set_mat_Speculaire(0.9, 0.9, 0.9, 1.0);
      terrain.set_shininess(0.01);

      masson.setTexname("fichiers/images/masson.png");
      masson.charger();
      masson.move(0.,0.,150.);

      hurault.setTexname("fichiers/images/hurault.png");
      hurault.charger();
      hurault.move(20.,0.,150.);
      hurault.colorer(255,255,255,1);

      /*
	light.set_Lumiere_Ambiente(a,b,c,d);   
	light.set_Lumiere_Diffuse(a,b,c,d);   
	light.set_Lumiere_Speculaire(a,b,c,d);
	light.set_Lumiere_Position(, 0., 200., 1.0);
      */
     
      charge=true;     
    }


  skybox.SetPosition((float)cam.getPosition()[0],
		     (float)cam.getPosition()[1],
		     (float)cam.getPosition()[2]);

  //skybox.SetRotation(0.0, 1.0, 1.0, 1.0);


  static ShaderLoader sloader;
  static Shader shade(sloader.loadFromFile("light.vert"),
		      sloader.loadFromFile("light.frag"));

  shade.setShader(false);
  skybox.Activate();

  if(k > 1000)
    {
      k = 0;
    }
  light.set_Lumiere_Position(k, k, 200., 1.0);
  k += 1.5;

  glEnable(GL_NORMALIZE);

 
  shade.setShader(true);

  light.ActiveLight();
  /* si vu navette alors */
  if(choice == 1){
  
    /* on dessine tous les objets sauf la navette */
    station.dessiner(1.0);
    terrain.dessiner();
    tricep.move(25.,25.,107.);
    tricep.dessiner(4.);
     
  
   
    /* on place la camera derriere l'objet */
    if(firstNav){
      CoordAux[0]=navette.getPosX();
      CoordAux[1]=navette.getPosY();
      CoordAux[2]=navette.getPosZ();
      navette.setAngleZ(anglY-90.);
      navette.setAngleY(anglX);
      cam.setPosition(CoordAux);
    }
    firstNav=false;
    firstSta=true;
    navette.move(0.01,0.,0.);
   
    //navette.rotate(0.,0.,0.);
    glPushMatrix();
    navette.rotate(0.,0.,0.);
    glTranslatef(cam.getTarget()[0]+cam.getForward()[0]+0.01,cam.getTarget()[1]+cam.getForward()[1],cam.getTarget()[2]+cam.getForward()[2]);
    glRotatef(anglY-90,0.,0.,1.);    
    glRotatef(-anglX,1.,0.,0.);
   
    navette.dessiner(0.05);
    
    glPopMatrix();
   
    //navette.setAngleZ(anglY-90);
    //navette.setAngleX(-anglX);
   
    navette.move(cam.getPosition()[0],cam.getPosition()[1],cam.getPosition()[2]);
   
   
  }

  /* si station alors */
  if(choice == 2){
  
    /* on dessine tous les objets sauf la station */
    navette.dessiner(0.05);
    terrain.dessiner();
    tricep.move(25.,25.,107.);
    tricep.dessiner(4.);
   
   
  
  
  
   
    /* on place la camera derriere l'objet */
    if(firstSta){
      CoordAux[0]=station.getPosX();
      CoordAux[1]=station.getPosY();
      CoordAux[2]=station.getPosZ();
     
      cam.setPosition(CoordAux);
    }
    firstSta=false;
    firstNav=true;
    station.move(0.01,0.,0.);
    station.rotate(0.,0.,0.);
    glPushMatrix();
    glTranslatef(cam.getTarget()[0]+cam.getForward()[0]+0.01,cam.getTarget()[1]+cam.getForward()[1],cam.getTarget()[2]+cam.getForward()[2]);
    glRotatef(anglY-90.,0.,0.,1.);    
    glRotatef(-anglX,1.,0.,0.);
   
    station.dessiner(0.1);
   
    glPopMatrix();
   
    //station.setAngleZ(anglY-90.);
    //station.setAngleX(-anglX);
   
    station.move(cam.getPosition()[0],cam.getPosition()[1],cam.getPosition()[2]);
   
   
  }
  /* si free fly */
  if(choice ==0){
   
    firstNav=true;
    firstSta=true;
    navette.dessiner(0.05);
    station.dessiner(1.0);
    terrain.dessiner();
    tricep.move(25.,25.,107.);
    tricep.dessiner(4.);
  }
  light.DisactiveLight();
 
 

  //skybox.Disactivate();
  shade.setShader(false);
  masson.dessiner();
  hurault.dessiner();
  glDisable(GL_NORMALIZE);

  myrec.write_ppmfile();
  glutSwapBuffers();
}



void DemoWindow::CallBackReshapeFunc(int w, int h){
    
  R=0.0;
  
  idle=0;
  glViewport(0, 0, w, h); 
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  float rapport=(GLfloat) w/(GLfloat) h;

  //float height= h*rapport;
  //float width= w*rapport;
  cout<< "Angle :" <<(2*(180/PI)*atan( ((float)h/height) * tan(35*(PI/180)) ))<<endl;
  gluPerspective((2*(180/PI)*atan( ((float)h/height) * tan(35*(PI/180)) )),rapport,0.1,100000000);
  
  //glOrtho(-2.0*(float)(w/width),2.0*(float)(w/width),-2.0*(float)(h/height),2.0*(float)(h/height),4.0,-10.0);
	
  glMatrixMode(GL_MODELVIEW);
  
  CallBackDisplayFunc();
}

void DemoWindow::CallBackIdleFunc(void){
  angle+=inc;
  CallBackDisplayFunc();
}

void DemoWindow::CallBackMouseFunc(int button, int state, int x, int y){
  switch(button){
  case GLUT_RIGHT_BUTTON:
    if(state==GLUT_DOWN)
      StartSpinning(refglutMaster);break;
    //case GLUT_MIDDLE_BUTTON:
  case GLUT_LEFT_BUTTON :
    // if(state==GLUT_DOWN)
      // refglutMaster->DisableIdleFunction();break;
  default :break;
  }
  CallBackDisplayFunc();
}

void DemoWindow::StartSpinning(GlutMaster * glutMaster){
  glutMaster->SetIdleToCurrentWindow();
  glutMaster->EnableIdleFunction();
  idle=1;
}	

void DemoWindow::CallBackKeyboardFunc(unsigned char key, int x, int y){
  GLfloat a=0,b=0,c=0,d=0;
  switch ( key ) {
	
  case 'z'  : cam._keystates[EZ]=true; 				
    break; 	
  case 's'  : cam._keystates[ES]=true;  				
    break;	
  case 'q'  : cam._keystates[EQ]=true; 				
    break; 	
  case 'd'  : cam._keystates[ED]=true; 				
    break; 
	
  case '+'  : cam._keystates[Eplus]=true; 				
    break; 	
  case '-'  : cam._keystates[Emoins]=true;				
    break; 
	
  case 'o'  : cam._relY-=5; if(anglX>=-90.)anglX-=1.;			
    break;	
  case 'k'  : cam._relX-=5;  anglY+=1.; 		
    break;	
  case 'l'  : cam._relY+=5;  if(anglX<=90.)anglX+=1.; 
    break; 
  case 'm'  : cam._relX+=5;  anglY-=1.;
    break; 
	
  case 'w'  : cam._keystates[EW]=true; 				
    break;

  case 'n'  : blight=!blight;				
    break;

  case '8'  : 
    myrec.switch_recording("VideoDemo_hurault_masson");
    break;

  case '9'  :
    myrec.treat_recording();system("rm *.ppm *.log");
    break;
			
  case 'a'  : idle=!idle;
    StartSpinning(refglutMaster);
    break;	
  case 0x1B : exit(0);

  }		
}	
	

   






